import java.util.ArrayList;
import java.util.List;

import lejos.nxt.Button;
import lejos.nxt.I2CPort;
import lejos.nxt.MotorPort;
import lejos.nxt.NXTMotor;
import lejos.nxt.SensorPort;
import lejos.nxt.Sound;
import lejos.util.Delay;

public class Lights {

    private static I2CPort portLights;

    private static final int POWER = 80;
    private static final int DEGREES = 15;

    public static void main(String[] args) throws InterruptedException {
        // init the sensor
        portLights = SensorPort.S4;
        portLights.i2cEnable(I2CPort.STANDARD_MODE);

        // text to be displayed as byte array
        byte[] text = buildByteArray("Hello d[-_-]b World!");

        // give some time to prepare taking a photo
        countdown();

        // start the motor and let it go for a second
        NXTMotor m1 = new NXTMotor(MotorPort.A);
        NXTMotor m2 = new NXTMotor(MotorPort.B);

        // poor-man approach to calibrate both motors
        m2.setPower((int) (POWER * 0.94));
        m1.setPower(POWER);

        // short delay
        Delay.msDelay(1000);

        // start measuring the tacho count
        int degrees = m1.getTachoCount();
        int index = 0;

        while (true) {
            int currentDegrees = m1.getTachoCount();

            // if the motor turned DEGREES degrees, switch
            // to next LED pattern
            if (currentDegrees - degrees > DEGREES) {
                index++;

                if (index == text.length) {
                    break;
                }
                degrees = currentDegrees;
            }

            sendByte(text[index]);

            // interrupt if escape button is pressed
            if (Button.ESCAPE.isDown()) {
                break;
            }
        }

        // turn out lights and stop motor
        sendByte((byte) 0x00);
        m1.stop();
        m2.stop();
    }

    /**
     * Send one byte to the LED bar.
     * 
     * @param character
     *            -- a bit pattern to display
     */
    private static void sendByte(byte character) {
        byte[] data = { (byte) (~character & 0xff) };
        portLights.i2cTransaction(0x70, data, 0, 1, null, 0, 0);
    }

    // turn string into array of byte patterns
    private static byte[] buildByteArray(String text) {

        // as characters have different width, we need to
        // iterate over string
        List<Byte> bytes = new ArrayList<Byte>();
        for (char aChar : text.toCharArray()) {
            byte[] charBytes = BitmapFont8px.getCharacterAsBitmap(aChar);

            for (byte aByte : charBytes) {
                bytes.add(aByte);
            }

            // add space between characters
            bytes.add((byte) 0x00);
            bytes.add((byte) 0x00);
        }

        // convert list to array
        byte[] res = new byte[bytes.size()];
        int i = 0;
        for (Byte aByte : bytes) {
            res[i++] = aByte;
        }
        return res;
    }

    public static void countdown() {
        Sound.beep();
        Delay.msDelay(3000);
        Sound.beep();
        Delay.msDelay(2000);
        Sound.beep();
        Delay.msDelay(1000);
    }
}

